/*
 *   Clovis
 *   Copyright (C) 2008 SFWOL
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "CString.h"

namespace clovis {

	namespace core {

        CString::CString( std::string name , std::string value ) : ClovisVariable( name ){
            this->value = value;
        }


		CString::CString() : ClovisVariable(){

			this->value = "";

		}

		CString::CString(std::string value) : ClovisVariable(){

			this->value = value;

		}

		CString::CString(const char *value) : ClovisVariable(){

			this->value = value;

		}

		std::string CString::getClass(){

			return "CString";

		}

		void CString::operator = (std::string value){

			this->value = value;

		}

		void CString::operator = (CString value){

			this->value = value.value;

		}

        void CString::operator = (const char *value){

			this->value = value;

		}

		CString CString::operator + (CString value){

            return (CString(this->value + value.value));

		}

		CString CString::operator + (CInteger value){

			return (CString(this->value + value.toString()));

		}

		CString CString::operator + (CFloat value){

			return (CString(this->value + value.toString()));

		}

		void CString::operator += (CString to_add){

			this->value = this->value + to_add.value;

		}

		void CString::operator += (CInteger to_add){

			this->value = this->value + to_add.toString();

		}

		void CString::operator += (CFloat to_add){

			this->value = this->value + to_add.toString();

		}

		bool CString::operator == (CString compare_to){

			if(this->value == compare_to.value)
				return true;
			else
				return false;

		}

		bool CString::operator == (CInteger compare_to){

			if(this->value == compare_to.toString())
				return true;
			else
				return false;

		}

		bool CString::operator == (CFloat compare_to){

			if(this->value == compare_to.toString())
				return true;
			else
				return false;

		}

		bool CString::operator != (CString compare_to){

			if(this->value != compare_to.value)
				return true;
			else
				return false;

		}

		bool CString::operator != (CInteger compare_to){

			if(this->value != compare_to.toString())
				return true;
			else
				return false;

		}

		bool CString::operator != (CFloat compare_to){

			if(this->value != compare_to.toString())
				return true;
			else
				return false;

		}

		std::string CString::toStdString(){

			return this->value;

		}

		void CString::clear(){

		    this->value.clear();

		}

		const char* CString::toCharArray(){

			return this->value.c_str();

		}

		void CString::wash(CString skip){

			// Looking for the first "real" character
			int begining = this->value.find_first_not_of(skip.toCharArray());

			// Looking for the last "real" character (not white space or linebreak)
			int end = this->value.length() - this->value.find_first_not_of(skip.toCharArray());

			if(this->value.length() > 0){

				// We only keep the "real" content
				if(begining != end && begining > 0 && end > 0){

					this->value = this->value.substr(begining, end);

				}

			}

		}

		std::vector<CString> CString::explode(CString delimiter){

			std::vector<CString> tmp;
			int position = -1;

			std::string tmp_string = this->value;
			std::string new_part = "";

			position = tmp_string.find_first_of(delimiter.toCharArray());

			// If there is at least one delimiter in the string we have to loop, else, we just have to return a blank vector
			if(position != -1){

				while(position != -1){

					new_part.clear();

					new_part = tmp_string.substr(0, position);
					tmp_string = tmp_string.substr(position + 1, tmp_string.length() - position);

					if(new_part != "") // We don't need empty strings
						tmp.push_back(new_part);

					position = tmp_string.find_first_of(delimiter.toCharArray());

				}

				tmp.push_back(tmp_string); // Fetching the last part (without delimiter)

			}else{

				// There is no delimiter so we should return a 1 item vector
				tmp.push_back(this->value);

			}

			return tmp;

		}

		CString CString::implode(std::vector<CString> cstring_vector, CString delimiter){

			CString tmp = "";

			for(unsigned int bcl = 0 ; bcl < cstring_vector.size() ; bcl++) {

				tmp = tmp + cstring_vector[bcl];

				if(bcl != cstring_vector.size() - 1)
					tmp = tmp + delimiter;

			}

			return tmp;

		}

		char CString::charAt(CInteger position){

			return this->value[position.toInt()];

		}

		CInteger CString::size(){

            CInteger tmp = this->value.size();
            return tmp;

		}

		CInteger CString::maxSize(){

			CInteger temp = this->value.capacity();
			return temp;

		}

		bool CString::isEmpty(){

			return this->value.empty();

		}

		void CString::insert(CString string_to_add){

		}

		void CString::replace(CInteger selection_beginning, CInteger selection_end, CString replace_with){

		}

		void CString::remove(CInteger selection_beginning, CInteger selection_end){

		}

		std::vector<CInteger> CString::find(CString element){

			std::vector<CInteger> elements;
			return elements;

		}

		CInteger CString::findFirstOf(CString element){

			CInteger value = this->value.find_first_of(element.toStdString());

			return value;

		}

		CInteger CString::findLastOf(CString element){

			CInteger value = this->value.find_last_of(element.toStdString());

			return value;

		}

		CInteger CString::findFirstNotOf(CString element){

			CInteger value = this->value.find_first_not_of(element.toStdString());

			return value;

		}

		CInteger CString::findLastNotOf(CString element){

			CInteger value = this->value.find_last_not_of(element.toStdString());

			return value;

		}

		bool CString::equals(CString string_to_compare_to){

			return false;

		}

		CString CString::substr(CInteger begining, CInteger length){

			CString tmp = this->value.substr(begining.toInt(), length.toInt());

			return tmp;

		}

		CFloat CString::toCFloat(){

			float value = 0.0;

			std::stringstream ss(this->value);
   			ss >> value;

   			CFloat tmp = value;

			return tmp;

		}

		CInteger CString::toCInteger(){

			int value = 0;

			std::stringstream ss(this->value);
   			ss >> value;

			CInteger tmp = value;

			return tmp;

		}

	};

};
